package com.founder.barcode.outerapp.util;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import com.founder.barcode.outerapp.service.IScheduleService;

public class ScheduledExecutorUtil {
    
    private class LockFuture {
        private Boolean finish = true;
        
        public Boolean getFinish() {
            return finish;
        }

        public void setFinish(Boolean finish) {
            this.finish = finish;
        }

        private ScheduledFuture<?> scheduledFuture;
        
        public ScheduledFuture<?> getScheduledFuture() {
            return scheduledFuture;
        }

        public LockFuture(ScheduledFuture<?> scheduledFuture) {
            this.scheduledFuture = scheduledFuture;
        }
    }
    
    private class ScheduledRun implements Runnable{
        private IScheduleService scheduleService;
        
        private Object key;
        
        public ScheduledRun(IScheduleService scheduleService,Object key) {
            this.scheduleService = scheduleService;
            this.key = key;
        }
        
        public void run() {
            // TODO Auto-generated method stub
            LockFuture lock = map.get(this.key);
            synchronized (lock) {
                lock.setFinish(false);
                this.scheduleService.schedule();
                lock.setFinish(true);
                lock.notify();
            }
        }
    }
    
    private static Map<Object, LockFuture> map = new HashMap<Object, LockFuture>();
    
    private static ScheduledExecutorUtil instance = null;
    
    private ScheduledExecutorService scheduledService = null;
    
    private ScheduledExecutorUtil() {
        scheduledService = Executors.newScheduledThreadPool(10);
    }
    
    public static ScheduledExecutorUtil getInstance() {
        if(instance == null) {
            instance = new ScheduledExecutorUtil();
        }
        return instance;
    }
    
    public void stopScheduleTask(String key) throws InterruptedException {
        LockFuture lock = map.get(key);
        synchronized (lock) {
            while(!lock.getFinish()){
                lock.wait();
            }
            lock.getScheduledFuture().cancel(true);
            lock = null;
        }
    }
    
    public void startScheduleExecutor(IScheduleService service,Long initialDelay,Long period,Object key) {
        ScheduledFuture<?> scheduleService = scheduledService.
                scheduleAtFixedRate(new ScheduledRun(service, key), initialDelay, period, TimeUnit.MILLISECONDS);
        map.put(key,new LockFuture(scheduleService));
    }
    
    public void startScheduleExecutor(IScheduleService service,Long period,String key) {
        this.startScheduleExecutor(service, 0L, period, key);
    }
}
